package com.guo.todo.gateway.filter;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.guo.todo.common.response.Result;
import com.guo.todo.common.response.ResultEnum;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;

/**
 * @Auther: hotlove_linx
 * @Date: 2023/7/24 21:24
 * @Description:
 */
@Order(0)
@Component
public class AuthorizeFilter implements GlobalFilter {

    @Resource
    private RestTemplate restTemplate;

    @Value("${http.usercenter.service-name:}")
    private String serviceName;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        String path = exchange.getRequest().getURI().getPath();
        if (path.contains("/usercenter/credential/login")) {
            // 如果是登录接口绕过鉴权
            return chain.filter(exchange);
        }

        // 验证token是否有效
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        String terminal = exchange.getRequest().getHeaders().getFirst("terminal");

        // 如果请求头缺少token或者terminal则请求失败
        if (StringUtils.isBlank(token) || StringUtils.isBlank(terminal)) {

        }

        Result result = validToken(token, terminal);
        boolean valid = (Boolean) result.getData();
        if (!valid) {
            // 如果token验证不通过，说明token有问题
            Result failValidTokenResult = Result.fail(ResultEnum.INVALID_TOKEN.getCode(), result.getMessage());

            // 写回数据
            DataBuffer buffer = exchange.getResponse()
                    .bufferFactory()
                    .wrap(JSON.toJSONBytes(failValidTokenResult));

            return exchange.getResponse().writeWith(Flux.just(buffer));
        }

        return chain.filter(exchange);
    }

    private Result validToken(String token, String terminal) {
        String url = "http://"+serviceName+"/usercenter/credential/valid";
        HttpHeaders header = new HttpHeaders();
        header.setContentType(MediaType.APPLICATION_JSON);

        JSONObject params = new JSONObject();
        params.put("token", token);
        params.put("terminal", terminal);

        HttpEntity<String> request = new HttpEntity<>(JSON.toJSONString(params), header);

        return restTemplate.postForObject(url, request, Result.class);
    }
}
